#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

using namespace EpollModule;
class Connection;

using connection_t = std::shared_ptr<Connection>;

class Reactor 
{
    const static int event_num = 64;
    bool IsConnectionExist(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }

public:
    Reactor():_isrunning(false), _epoller(std::make_unique<Epoller>())
    {
        _epoller->Init();
    }


    void InsertConnection(connection_t conn)
    {
        auto iter = _connections.find(conn->Sockfd());
        if(iter == _connections.end())
        {
            // 1. 把链接放到unordered_map中进行管理
            _connections.insert(std::make_pair(conn->Sockfd(), conn));
            // 2.把新连接，写透到内核的epoll中
            _epoller->Add(conn->Sockfd(), conn->GetEvents());
            // 3.设置关联关系，让connection回指当前对象
            conn->SetOwner(this);
            LOG(LogLevel::DEBUG) << "insert connection sucess fd:" << conn->Sockfd();
        }
    }

    void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        if(IsConnectionExist(sockfd))
        {
            // 修改用户层connection的事件
            uint32_t events = (readable? EPOLLIN : 0) | (writeable? EPOLLOUT : 0) | EPOLLET;
            _connections[sockfd]->SetEvents(events);
            // 写透到内核中
            _epoller->Update(sockfd, _connections[sockfd]->GetEvents());
        }
    }

    void DelConnection(int sockfd)
    {
        if(IsConnectionExist(sockfd))
        {
            // 1.从内核中移除sockfd的关心
            _epoller->Delete(sockfd);
            // 2。关闭特定描述符
            _connections[sockfd]->Close();
            // 3.从unordered_map中移除
            _connections.erase(sockfd);
        }
    }

    // 基于事件驱动的时间派发器
    void Dispatcher(int n)
    {
        for(int i = 0; i < n; i++)
        { 
            //LOG(LogLevel::DEBUG) << "epoll event " << i << " " << _revs[i].data.fd << " " << _revs[i].events;
            // 开始派发

            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;

            if((revents & EPOLLERR) || (revents & EPOLLHUP))
                revents = EPOLLIN | EPOLLOUT;

            // if (!IsConnectionExist(sockfd))
            // {
            //     LOG(LogLevel::DEBUG) << "epoll event " << sockfd << " not exist";
            // }

            if((revents & EPOLLIN) && IsConnectionExist(sockfd))
            {
                _connections[sockfd]->Recver();
            }
            if((revents & EPOLLOUT) && IsConnectionExist(sockfd))
            {
                _connections[sockfd]->Sender();
            }

        }
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, event_num, timeout);
        LOG(LogLevel::DEBUG) << "epoll wait return " << n;
        Dispatcher(n);
    }

    std::string DebugPrint()
    {
        std::string str = "Reactor管理的fd: ";
        for(auto &iter: _connections)
        {
            str += std::to_string(iter.first) + " ";
        }
        return str;
    }

    // void DebugPrint()
    // {
    //     std::cout << "###################" << std::endl;
    //     for(auto &conn : _connections)
    //     {
    //      
    //     }
    //     std::cout << "###################" << std::endl;
    //
    // }

    void Loop()
    {
        // LOG(LogLevel::DEBUG) << DebugPrint();
        // if (!IsConnectionExist(3))
        // {
        //     LOG(LogLevel::DEBUG) << "epoll event " << 3 << " not exist";
        // }

        _isrunning = true;
        int timeout = -1;
        int cnt = 0;
        while(_isrunning)
        {
            LoopOnce(timeout);
            //
        }
        _isrunning = false;
    }

    void Stop()
    {
        _isrunning = false;
    }
    
    ~Reactor() 
    {}
private:
    std::unique_ptr<Epoller> _epoller;
    std::unordered_map<int, connection_t> _connections; // 服务器内部所有的连接
    bool _isrunning;
    struct epoll_event _revs[event_num];
};